package test_package;

import org.openqa.selenium.Capabilities;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.ie.InternetExplorerDriver;

public class WebDriverFactory {

  // Factory settings

  private static String defaultHub = null;

  // Factory

  private static String key = null;
  private static WebDriver driver;

  public static WebDriver getDriver(String hub, Capabilities capabilities) {

    if (driver == null) {
      return newWebDriver(hub, capabilities);
    }

    String newKey = capabilities.toString() + ":" + hub;
    if (!newKey.equals(key)) {
      dismissDriver();
      key = newKey;
      return newWebDriver(hub, capabilities);
    }

    try {
      driver.getCurrentUrl();
    } catch (Throwable t) {
      t.printStackTrace();
      return newWebDriver(hub, capabilities);
    }

    return driver;
  }

  public static WebDriver getDriver(Capabilities capabilities) {
    return getDriver(defaultHub, capabilities);
  }

  public static void dismissDriver() {
    if (driver != null) {
      try {
        driver.quit();
        driver = null;
        key = null;
      } catch (WebDriverException ex) {
      }
    }
  }


  private static WebDriver newWebDriver(String hub, Capabilities capabilities) {
    driver =  createLocalDriver(capabilities);
    key = capabilities.toString() + ":" + hub;
    return driver;
  }

  private static WebDriver createLocalDriver(Capabilities capabilities) {
    String browserType = capabilities.getBrowserName();
    if (browserType.equals("firefox"))
      return new FirefoxDriver(capabilities);
    if (browserType.startsWith("internet explorer"))
      return new InternetExplorerDriver(capabilities);
    if (browserType.equals("chrome"))
      return new ChromeDriver(capabilities);
    throw new Error("Unrecognized browser type: " + browserType);
  }

  static {
    Runtime.getRuntime().addShutdownHook(new Thread() {
      public void run() {
        dismissDriver();
      }
    });
  }
}
